home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xwator / xwator.c < prev    next >
C/C++ Source or Header  |  1995-05-26  |  26KB  |  1,038 lines

  1. /*
  2.  * (c) Copyright Brian Chapman (bchapman@microsoft.com) and 
  3.  *               Ronald Joe Record (rr@sco.com)
  4.  *
  5.  * Authors - Brian Chapman and Ronald Joe Record
  6.  *
  7.  * Xwator is a simulation of sharks and fish with the fish "swimming"
  8.  * around and the sharks "eating" the fish. We added some rules to
  9.  * simulate evolution amongst both the sharks and the fish.
  10.  *
  11.  * MODIFICATION HISTORY
  12.  *
  13.  * S001 - 06 Sep 1990, sco!rr
  14.  *     - restore original display mode prior to exiting
  15.  * S002 - 06 Sep 1990, sco!rr
  16.  *    - adapted to work in graphics mode
  17.  * S003 - 09 Sep 1990, sco!rr
  18.  *    - added a bunch of options (set width, height, resolution,
  19.  *      Continue and infinite modes)
  20.  * S004 - 11 Sep 1990, sco!rr
  21.  *    - added display of population curves (-C option).
  22.  * S005 - 18 Sep 1990, sco!rr
  23.  *    - removed infinite mode and changed Continue to _Continue
  24.  *    - instead of erasing the whole curve display every PPL generations,
  25.  *      now just clear the next few columns ahead of where you're drawing.
  26.  * S006 - 19 Sep 1990, sco!rr
  27.  *    - ported to X using Motif widget set, Intrinsics, and Xlib
  28.  * S007 - 23 Sep 1990, sco!rr
  29.  *    - split out xwator.h; use XDrawLine() in clear_ahead();
  30.  *      use XtSetArg() & XtSetValues() to establish attachments dynamically;
  31.  *      add curve/nocurve buttons; use XFillRectangles() to draw when Rflag
  32.  *      is specified (i.e. each point is really a box).
  33.  * S008 - 23 May 1995, rr@sco.com
  34.  *  - ported to SCO OpenServer 5 and cleaned up a bit.
  35.  */
  36.  
  37. #include "xwator.h"
  38.  
  39. main(ac,av)
  40. int ac;
  41. char *av[];
  42. {
  43.     Widget toplevel;
  44.     int i;
  45.  
  46.     parseargs(ac,av);
  47.     init_data();
  48.     init_creatures();
  49.     toplevel = XtInitialize(av[0], "Wator", NULL, 0, 
  50.                           &ac, av);
  51.     framework = XtCreateManagedWidget("framework", 
  52.                           xmFormWidgetClass, toplevel, NULL, 0);
  53.     /*
  54.      * Create the widget to display the wator and register
  55.      * callbacks for resize and refresh.
  56.      */
  57.     canvas = XtCreateManagedWidget("drawing_canvas", 
  58.                      xmDrawingAreaWidgetClass, framework, NULL, 0);
  59.     fish_return = XtCreateManagedWidget("fish", 
  60.                      xmDrawingAreaWidgetClass, framework, NULL, 0);
  61.     shark_return = XtCreateManagedWidget("sharks", 
  62.                      xmDrawingAreaWidgetClass, framework, NULL, 0);
  63.     population = XtCreateManagedWidget("pop_curves", 
  64.                      xmDrawingAreaWidgetClass, framework, NULL, 0);
  65.     /* 
  66.      * Create the pushbutton widgets. 
  67.      */ 
  68.     button[0] =  XtCreateManagedWidget("go_button",
  69.                                  xmPushButtonWidgetClass,
  70.                                  framework, NULL, 0);
  71.     button[1] =  XtCreateManagedWidget("stop_button",
  72.                                  xmPushButtonWidgetClass,
  73.                                  framework, NULL, 0);
  74.     button[2] =  XtCreateManagedWidget("quit_button",
  75.                                  xmPushButtonWidgetClass,
  76.                                  framework, NULL, 0);
  77.     button[3] =  XtCreateManagedWidget("curve_button",
  78.                                  xmPushButtonWidgetClass,
  79.                                  framework, NULL, 0);
  80.  
  81.     init_canvas();  
  82.  
  83.     /*  
  84.      * Add callbacks. 
  85.      */ 
  86.     XtAddCallback(canvas, XmNexposeCallback, redisplay, Data); 
  87.     XtAddCallback(canvas, XmNresizeCallback, resize, Data); 
  88.     XtAddCallback(fish_return, XmNexposeCallback, redisplay, Fret); 
  89.     XtAddCallback(fish_return, XmNresizeCallback, resize, Fret); 
  90.     XtAddCallback(shark_return, XmNexposeCallback, redisplay, Sret);
  91.     XtAddCallback(shark_return, XmNresizeCallback, resize, Sret); 
  92.     XtAddCallback(population, XmNexposeCallback, redisplay, Pop); 
  93.     XtAddCallback(population, XmNresizeCallback, resize, Pop); 
  94.     XtAddCallback(button[0], XmNactivateCallback, start_swimming, NULL);
  95.     XtAddCallback(button[1], XmNactivateCallback, stop_swimming, NULL);
  96.     XtAddCallback(button[2], XmNactivateCallback, quit, NULL);
  97.     XtAddCallback(button[3], XmNactivateCallback, curves, NULL);
  98.  
  99.     XtRealizeWidget(toplevel);
  100.     curves();
  101.     resize(canvas, Data, (caddr_t)NULL);
  102.     resize(fish_return, Fret, (caddr_t)NULL);
  103.     resize(shark_return, Sret, (caddr_t)NULL);
  104.     resize(population, Pop, (caddr_t)NULL);
  105.     /* register the workproc */
  106.       work_proc_id = XtAddWorkProc(go, canvas);
  107.     XtMainLoop();
  108. }
  109.  
  110. init_data()
  111. {
  112.     lrtb_t ocean;
  113.     int h, w;
  114.     struct wator_cell *wp;
  115.     char *value;
  116.     XColor used, exact;
  117.     extern char *getenv();
  118.  
  119.     if((Data=(struct image_data *)malloc(sizeof(struct image_data)))==NULL){
  120.         fprintf(stderr,"Error malloc'ing Data. Exiting\n");
  121.         exit(-1);
  122.     }
  123.     if((Fret=(struct image_data *)malloc(sizeof(struct image_data)))==NULL){
  124.         fprintf(stderr,"Error malloc'ing Fret. Exiting\n");
  125.         exit(-1);
  126.     }
  127.     if((Sret=(struct image_data *)malloc(sizeof(struct image_data)))==NULL){
  128.         fprintf(stderr,"Error malloc'ing Sret. Exiting\n");
  129.         exit(-1);
  130.     }
  131.     if((Pop=(struct image_data *)malloc(sizeof(struct image_data)))==NULL){
  132.         fprintf(stderr,"Error malloc'ing Pop. Exiting\n");
  133.         exit(-1);
  134.     }
  135.     if((wator=(struct wator_cell **)malloc(HEIGHT*sizeof(wator)))==NULL) {
  136.         fprintf(stderr,"Error malloc'ing wator. Exiting\n");
  137.         exit(-1);
  138.     }
  139.  
  140.     if ((dpy = XOpenDisplay(getenv("DISPLAY")))==NULL) {
  141.         fprintf(stderr, " Error opening display. Exiting\n");
  142.         exit(-2);
  143.     }
  144.     if (DisplayPlanes(dpy, 0) == 1)
  145.         mono++;
  146.     colors[0] = water_icon = BlackPixel(dpy, 0);
  147.  
  148.     for(h=0; h<HEIGHT; h++)
  149.     {
  150.     if((wator[h]=(struct wator_cell *)malloc(WIDTH*sizeof(struct wator_cell)))==NULL) {
  151.         fprintf(stderr,"Error malloc'ing wator[%d]. Exiting\n",h);
  152.         exit(-1);
  153.     }
  154.         for(w=0; w<WIDTH; w++)
  155.         {
  156.             wp = &(wator[h][w]);
  157.             wp->creature = WATER;
  158.             wp->age = 0;
  159.             wp->mv = 1;
  160.             wp->ate = 0;
  161.             wp->blocked = 0;
  162.             wp->icon = water_icon;
  163.             wp->spec = water_spec;
  164.         }
  165.     }
  166.     value = XGetDefault(dpy, "Wator", "FishColor");
  167.     if (!value) value = "green";
  168.     XAllocNamedColor(dpy, DefaultColormap(dpy,0),value,&used,&exact); 
  169.     colors[1] = fish_icon = (mono) ? WhitePixel(dpy,0) : used.pixel;
  170.     value = XGetDefault(dpy, "Wator", "SharkColor");
  171.     if (!value) value = "yellow";
  172.     XAllocNamedColor(dpy, DefaultColormap(dpy,0),value,&used,&exact); 
  173.     colors[13] = shark_icon = (mono) ? WhitePixel(dpy,0) : used.pixel;
  174. }
  175.  
  176. init_creatures()
  177. {
  178.     int i, fish, x, limit;
  179.     int h, w;
  180.     struct wator_cell *wp;
  181.  
  182.     srand( time(0) );
  183.  
  184.     for(fish=0; fish<2; fish++)
  185.     {
  186.         if(fish)
  187.             limit = FISH_START;
  188.         else
  189.             limit = SHARK_START;
  190.         for(i=0; i<limit; i++)
  191.         {
  192.             do {
  193.                 w = rand() % WIDTH;    
  194.                 h = rand() % HEIGHT;    
  195.                 wp = &(wator[h][w]);
  196.             } while(wp->creature != WATER);
  197.  
  198.             if(fish)
  199.             {
  200.                 wp->creature = FISH;
  201.                 wp->age = rand() % FISH_SPAWN;
  202.                 wp->icon = fish_icon;
  203.                 wp->spec = 2;
  204.                 wp->rate = FISH_SPAWN;
  205.             }
  206.             else
  207.             {
  208.                 wp->creature = SHARK;
  209.                 wp->age = rand() % SHARK_SPAWN;
  210.                 wp->icon = shark_icon;
  211.                 wp->spec = 14;
  212.                 wp->rate = SHARK_STARVE;
  213.             }
  214.             wp->mv = 1;
  215.         }
  216.     }
  217. }
  218.  
  219. init_canvas()
  220. {
  221.     int i, y, wide, high;
  222.     Arg wargs[4];
  223.     XGCValues gcv;
  224.  
  225.     /*
  226.      * Set the size of the drawing areas.
  227.      */
  228.     MAX_X = XDisplayWidth(XtDisplay(canvas), XDefaultScreen(XtDisplay(canvas)));
  229.     MAX_Y = XDisplayHeight(XtDisplay(canvas), XDefaultScreen(XtDisplay(canvas)));
  230.     if (Eflag) {
  231.         WRES = MAX_X / WIDTH;
  232.         HRES = MAX_Y / HEIGHT;
  233.     }
  234.     if (!Cflag) {
  235.         if ((wide=(2*WIDTH*WRES)) > MAX_X)
  236.             wide = MAX_X - MARGIN;
  237.         if ((high=(3*HEIGHT*HRES)) > MAX_Y)
  238.             high = MAX_Y - MARGIN;
  239.     }
  240.     else {
  241.         if ((wide=(WIDTH*WRES)+MARGIN) > MAX_X)
  242.             wide = MAX_X - MARGIN;
  243.         if ((high=(HEIGHT*HRES)+MARGIN) > MAX_Y)
  244.             high = MAX_Y - MARGIN;
  245.     }
  246.     XtSetArg(wargs[0], XtNwidth, wide);
  247.     XtSetArg(wargs[1], XtNheight, high);
  248.     XtSetValues(framework, wargs,2);
  249.  
  250.     for (i=0; i< MAXCOLOR; i++) {
  251.         Data->gc[i] = XCreateGC(XtDisplay(canvas),
  252.                          DefaultRootWindow(XtDisplay(canvas)),
  253.                          0, (XGCValues *)NULL); 
  254.         XSetForeground(XtDisplay(canvas), Data->gc[i], get_color_index(i));
  255.         Fret->gc[i] = Sret->gc[i] = Pop->gc[i] = Data->gc[i];
  256.     }
  257.     Data->width = wide; Data->height = high;
  258.     Pop->width = wide; Pop->height = high;
  259.     Fret->width = wide; Fret->height = high;
  260.     Sret->width = wide; Sret->height = high;
  261.     /* Create a graphics context with foreground=background for erasing */
  262.     gcv.foreground = gcv.background = BlackPixel(dpy, 0);
  263.     Egc = XCreateGC(XtDisplay(canvas),
  264.                          DefaultRootWindow(XtDisplay(canvas)),
  265.                          GCForeground | GCBackground, &gcv); 
  266.     /*
  267.      *  Initialize the pixmaps to all the same size.
  268.      */
  269.     Data->pix= XCreatePixmap(XtDisplay(canvas), 
  270.             DefaultRootWindow(XtDisplay(canvas)),
  271.             Data->width, Data->height, 
  272.             DefaultDepthOfScreen(XtScreen(canvas)));
  273.     Fret->pix= XCreatePixmap(XtDisplay(fish_return), 
  274.             DefaultRootWindow(XtDisplay(fish_return)),
  275.             Data->width, Data->height, 
  276.             DefaultDepthOfScreen(XtScreen(fish_return)));
  277.     Sret->pix= XCreatePixmap(XtDisplay(shark_return), 
  278.             DefaultRootWindow(XtDisplay(shark_return)),
  279.             Data->width, Data->height, 
  280.             DefaultDepthOfScreen(XtScreen(shark_return)));
  281.     Pop->pix= XCreatePixmap(XtDisplay(population), 
  282.             DefaultRootWindow(XtDisplay(population)),
  283.             Data->width, Data->height, 
  284.             DefaultDepthOfScreen(XtScreen(population)));
  285.     /* Clear the newly created pixmaps */
  286.     XFillRectangle(XtDisplay(canvas), Data->pix, Egc, 0, 0, 
  287.                    Data->width,  Data->height);
  288.     XFillRectangle(XtDisplay(fish_return), Data->pix, Egc, 0, 0, 
  289.                    Data->width,  Data->height);
  290.     XFillRectangle(XtDisplay(shark_return), Data->pix, Egc, 0, 0, 
  291.                    Data->width,  Data->height);
  292.     XFillRectangle(XtDisplay(population), Data->pix, Egc, 0, 0, 
  293.                    Data->width,  Data->height);
  294.     /* calculate offsets */
  295.     xoff = (Data->width - (WIDTH*WRES)) / 2;
  296.     yoff = (Data->height - (HEIGHT*HRES)) / 2;
  297.     if (xoff < 0)
  298.         xoff = 0;
  299.     if (yoff < 0)
  300.         yoff = 0;
  301.     AHEAD = Data->width / 10;
  302.     /* zero the point buffer */
  303.     init_buffer();
  304. }
  305.  
  306. void 
  307. resize(w, data, call_data)
  308. Widget         w;
  309. struct image_data    *data;
  310. caddr_t        call_data;
  311. {
  312.     Arg wargs[10];
  313.     /*  
  314.      *   Get the new window size.
  315.      */   
  316.     XtSetArg(wargs[0], XtNwidth,  &data->width);
  317.     XtSetArg(wargs[1], XtNheight, &data->height);
  318.     XtGetValues(w, wargs, 2);
  319.     /*
  320.      * Clear the window.
  321.      */
  322.      if(XtIsRealized(w))
  323.              XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, TRUE);
  324.     /*
  325.      *  Free the old pixmap and create a new pixmap 
  326.      *  the size of the window.
  327.      */
  328.     if(data->pix)
  329.            XFreePixmap(XtDisplay(w), data->pix);
  330.     data->pix= XCreatePixmap(XtDisplay(w),
  331.                              DefaultRootWindow(XtDisplay(w)),
  332.                              data->width, data->height, 
  333.                              DefaultDepthOfScreen(XtScreen(w)));
  334.     XFillRectangle(XtDisplay(w), data->pix, Egc, 0, 0, 
  335.                    data->width,  data->height);
  336.     XCopyArea(XtDisplay(w), data->pix, XtWindow(w), 
  337.             Data->gc[2], 0, 0, data->width, data->height, 0, 0);
  338.     /* re-calculate offsets */
  339.     if (Eflag) {
  340.         WRES = data->width / WIDTH;
  341.         HRES = data->height / HEIGHT;
  342.     }
  343.     xoff = (data->width - (WIDTH*WRES)) / 2;
  344.     yoff = (data->height - (HEIGHT*HRES)) / 2;
  345.     if (xoff < 0)
  346.         xoff = 0;
  347.     if (yoff < 0)
  348.         yoff = 0;
  349.     AHEAD = Pop->width / 10;
  350. }
  351.  
  352. void 
  353. redisplay (w, data, call_data)
  354. Widget          w;
  355. struct image_data     *data;
  356. XmDrawingAreaCallbackStruct    *call_data;
  357. {
  358.     XExposeEvent  *event = (XExposeEvent *) call_data->event;
  359.     /*
  360.      * Extract the exposed area from the event and copy
  361.      * from the saved pixmap to the window.
  362.      */
  363.     if(data->pix == (Pixmap)NULL)
  364.         data->pix= XCreatePixmap(XtDisplay(w), DefaultRootWindow(XtDisplay(w)),
  365.                   data->width, data->height, DefaultDepthOfScreen(XtScreen(w)));
  366.     XCopyArea(XtDisplay(w), data->pix, XtWindow(w), Data->gc[2], 
  367.            event->x, event->y, event->width, event->height, 
  368.            event->x, event->y);
  369. }
  370.  
  371. display()
  372. {
  373.     int h, w;
  374.     struct wator_cell *wp;
  375.  
  376.     for(h=0; h<HEIGHT; h++)
  377.     {
  378.         for(w=0; w<WIDTH; w++)
  379.         {
  380.             wp = &(wator[h][w]);
  381.             if(wp->mv)
  382.             {
  383.                 switch(wp->creature)
  384.                 {
  385.                 case WATER:
  386.                     draw_icon(h, w, water_spec);
  387.                     /*
  388.                      * This may look odd, it is a
  389.                      * performance kluge.
  390.                      */
  391.                     move_water(h, w);
  392.                     break;
  393.                 case FISH:
  394.                     draw_icon(h, w, wp->spec);
  395.                     break;
  396.                 case SHARK:
  397.                     draw_icon(h, w, wp->spec);
  398.                     break;
  399.                 }
  400.                 wp->mv = 0;
  401.             }
  402.         }
  403.     }
  404. }
  405.  
  406. draw_icon(h, w, spec)
  407. int spec;
  408. {
  409.     static int i,j,H,W;
  410.  
  411.     if (Rflag) {    /* We've set the resolution to something other than 1 */
  412.         H=h*HRES;
  413.          W=w*WRES;
  414.         buffer_box(canvas,Data,spec,xoff+W,yoff+H);
  415.     }
  416.     else
  417.         buffer_bit(canvas,Data,spec, xoff+w, yoff+h);
  418. }
  419.  
  420. Boolean
  421. go(W, data, call_data)
  422. Widget          W;
  423. struct image_data     *data;
  424. XmDrawingAreaCallbackStruct    *call_data;
  425. {
  426.     int h, w;
  427.     struct wator_cell *wp;
  428.     int fish_left=0, shark_left=0;
  429.  
  430.     for(h=0; h<HEIGHT; h++)
  431.     {
  432.         for(w=0; w<WIDTH; w++)
  433.         {
  434.             wp = &(wator[h][w]);
  435.             if(FISH == wp->creature && !wp->mv)
  436.             {
  437.                 if(!wp->blocked)
  438.                 {
  439.                     move_fish(h, w, wp);
  440.                     ++fish_left;
  441.                 }
  442.                 else if(++wp->blocked > FISH_CRUSH)
  443.                 {
  444.                     wp->creature = WATER;
  445.                     wp->mv = 1;
  446.                 }
  447.             }
  448.         }
  449.     }
  450.  
  451.     for(h=0; h<HEIGHT; h++)
  452.     {
  453.         for(w=0; w<WIDTH; w++)
  454.         {
  455.             wp = &(wator[h][w]);
  456.             if(SHARK == wp->creature && !wp->mv) {
  457.                 move_shark(h, w, wp);
  458.                 ++shark_left;
  459.             }
  460.         }
  461.     }
  462.     display();
  463.     generations++;
  464.     if (Cflag)
  465.         cdisplay();
  466.     flush_buffer();
  467.     if (fish_left)
  468.         return FALSE;
  469.     else
  470.         return TRUE;
  471. }
  472.  
  473. xy_t moves[8] ={ {0,-1}, {1,-1}, {1,0}, {1,1},        /*   7  0  1    */
  474.         {0,1}, {-1,1}, {-1,0}, {-1,-1} };    /*   6  +  2    */
  475.                             /*   5  4  3    */
  476.  
  477. struct wator_cell *
  478. move(m, h, w)
  479. int m;
  480. int h, w;
  481. {
  482.     int hh, ww;
  483.  
  484.     if(0==h && (7==m || 0==m || 1==m) )
  485.         hh = HEIGHT-1;
  486.     else if(HEIGHT-1==h && (3==m || 4==m || 5==m) )
  487.         hh = 0;
  488.     else
  489.         hh = h + moves[m].y;
  490.  
  491.     if(0==w && (m==5 || 6==m || 7==m) )
  492.         ww = WIDTH-1;
  493.     else if(WIDTH-1==w && (1==m || 2==m || 3==m) )
  494.         ww = 0;
  495.     else
  496.         ww = w + moves[m].x;
  497.  
  498.     return( &(wator[hh][ww]) );
  499. }
  500.  
  501. struct wator_cell *
  502. find_cell(h, w, creature)
  503. int h, w;
  504. {
  505.     int m;
  506.     int mm;
  507.     struct wator_cell *wp;
  508.     int hh, ww;
  509.  
  510.     mm = rand() % 8;
  511.  
  512.     for(m=(mm+1)%8; m!=mm; m=(m+1)%8)
  513.     {
  514.         wp = move(m, h, w);
  515.         if(creature == wp->creature)
  516.             return(wp);
  517.     }
  518.     return(0);
  519. }
  520.  
  521. move_fish(h, w, old)
  522. struct wator_cell *old;
  523. {
  524.     struct wator_cell *new;
  525.     int x, dir;
  526.  
  527.     old->age += 1;
  528.     if(0 == (new = find_cell(h, w, WATER)))
  529.     {
  530.         old->blocked = 1;
  531.         return(0);
  532.     }
  533.  
  534.     old->mv = 1;
  535.     *new = *old;
  536.     if(new->rate > new->age)
  537.         old->creature = WATER;
  538.     else
  539.     {
  540.         old->age = 0;
  541.         new->age = -1;
  542.         if(0 == rand() % FISH_MUTATE)
  543.         {
  544.  
  545.             if(1 == rand()%2)
  546.             {
  547.                 if(new->rate < 25)
  548.                     ++new->rate;
  549.             }
  550.             else
  551.             {
  552.                 if(new->rate > 1)
  553.                     --new->rate;
  554.             }
  555.             new->icon=get_color_index((new->rate % 7) + 1);
  556.             new->spec=(new->rate % 7) + 1;
  557.         }
  558.     }
  559. }
  560.  
  561. move_water(h, w)        /* clear the blocked fish around water */
  562. int h, w;
  563. {
  564.     int m, hh, ww;
  565.     struct wator_cell *wp;
  566.  
  567.     for(m=0; m<8; ++m)
  568.     {
  569.         wp = move(m, h, w);
  570.         if(wp->creature == FISH)
  571.             wp->blocked = 0;
  572.     }
  573. }
  574.  
  575. move_shark(h, w, old)
  576. struct wator_cell *old;
  577. {
  578.     struct wator_cell *new;
  579.  
  580.     old->age += 1;
  581.     old->ate += 1;
  582.  
  583.     if(0 != (new = find_cell(h, w, FISH)))
  584.         old->ate = 0;
  585.     else
  586.         if(0 == (new = find_cell(h, w, WATER)))
  587.             return;
  588.  
  589.     old->mv = 1;
  590.     if(old->ate >= old->rate)    /* STARVE */
  591.     {
  592.         old->creature = WATER;
  593.         return;
  594.     }
  595.     *new = *old;
  596.     if(SHARK_SPAWN > new->age)
  597.         old->creature = WATER;
  598.     else
  599.     {
  600.         old->age = 0;
  601.         new->age = -1;
  602.         new->ate = 0;
  603.         if(0 == rand() % SHARK_MUTATE)
  604.         {
  605.  
  606.             if(1 == rand()%2)
  607.             {
  608.                 if(new->rate < 25)
  609.                     ++new->rate;
  610.             }
  611.             else
  612.             {
  613.                 if(new->rate > 0)
  614.                     --new->rate;
  615.             }
  616.             new->icon = get_color_index((new->rate % 8) + 8);
  617.             new->spec = (new->rate % 8) + 8;
  618.         }
  619.     }
  620. }
  621.  
  622. int oldfish[15] = {0};
  623.  
  624. cdisplay()
  625. {
  626.     int h, w;
  627.     struct wator_cell *wp;
  628.     int numfish[15]; 
  629.     int fish_total, shark_total;
  630.  
  631.     fish_total = shark_total = 0;
  632.     for(h=0; h<15; h++)
  633.         numfish[h] = 0;
  634.     /* Get a count of the fish and shark totals */
  635.     for(h=0; h<HEIGHT; h++)
  636.     {
  637.         for(w=0; w<WIDTH; w++)
  638.         {
  639.             wp = &(wator[h][w]);
  640.             switch(wp->creature)
  641.             {
  642.             case WATER:
  643.                 break;
  644.             case FISH:
  645.                 ++numfish[wp->spec-1];
  646.                 ++fish_total;
  647.                 break;
  648.             case SHARK:
  649.                 ++numfish[wp->spec-1];
  650.                 ++shark_total;
  651.                 break;
  652.             }
  653.         }
  654.     }
  655.     /* Display the fish population curves */
  656.     for(h=0; h<7; h++) {
  657.         /* first, the return map (nth vs (n-1)st generations */
  658.         if (Pflag) {
  659.         ega_bit(fish_return,Fret,h,
  660.             ((oldfish[h] * Fret->width)+
  661.             (3*(oldfish[h]-numfish[h])*Fret->width))/ALLCELLS,
  662.             ((numfish[h] * Fret->height) / ALLCELLS));
  663.         }
  664.         oldfish[h] = numfish[h];
  665.         /* next, simply plot population vs time */
  666.         if (numfish[h] > 0) {
  667.             ega_bit(population,Pop,h,
  668.             (generations % Pop->width),
  669.             Pop->height - ((numfish[h]*Pop->height)/ALLCELLS));
  670.         }
  671.     }
  672.     /* Display the shark population curves */
  673.     for(h=7; h<15; h++) {
  674.         /* first, the return map (nth vs (n-1)st generations */
  675.         if (Pflag) {
  676.         ega_bit(shark_return,Sret,h,
  677.             ((oldfish[h] * Sret->width) / SOMECELLS)
  678.             +(((oldfish[h]-numfish[h])*Sret->width)/SOMECELLS),
  679.             ((numfish[h] * Sret->height) / SOMECELLS));
  680.         }
  681.         oldfish[h] = numfish[h];
  682.         /* next, simply plot population vs time */
  683.         if (numfish[h] > 0) {
  684.         ega_bit(population,Pop,h,
  685.             generations % Pop->width,
  686.             Pop->height-((2*numfish[h]*Pop->height)/ALLCELLS));
  687.         }
  688.     }
  689.     /* lastly, do the population vs time plot for total fish & sharks */
  690.     ega_bit(population,Pop,fish_spec, generations % Pop->width,
  691.             Pop->height-((fish_total*Pop->height)/ALLCELLS));
  692.     ega_bit(population,Pop,shark_spec, generations % Pop->width,
  693.             Pop->height-((shark_total*Pop->height)/SOMECELLS));
  694.     clear_ahead(generations % Pop->width);
  695. }
  696.  
  697. parseargs(ac,av)
  698. int ac;
  699. char *av[];
  700. {
  701.     int c;
  702.     extern int optind;
  703.     extern char *optarg;
  704.  
  705.     while ((c=getopt(ac,av,"CEPeiuA:M:R:S:T:w:h:m:s:t:")) != EOF)
  706.     {    switch(c)
  707.         {
  708.         case 'A':
  709.             AHEAD=atoi(optarg);
  710.             break;
  711.         case 'C':
  712.             Cflag=0;
  713.             break;
  714.         case 'E':
  715.             Eflag++;
  716.             Cflag=1;
  717.             break;
  718.         case 'M':
  719.             SHARK_MUTATE=atoi(optarg);
  720.             break;
  721.         case 'P':
  722.             Pflag = (!Pflag);
  723.             break;
  724.         case 'R':
  725.             WRES=HRES=atoi(optarg);
  726.             Rflag++;
  727.             break;
  728.         case 'S':
  729.             SHARK_SPAWN=atoi(optarg);
  730.             break;
  731.         case 'T':
  732.             SHARK_STARVE=atoi(optarg);
  733.             break;
  734.         case 'e':
  735.             eflag++;
  736.             break;
  737.         case 'h':
  738.             HEIGHT=atoi(optarg);
  739.             break;
  740.         case 'm':
  741.             FISH_MUTATE=atoi(optarg);
  742.             break;
  743.         case 's':
  744.             FISH_SPAWN=atoi(optarg);
  745.             break;
  746.         case 't':
  747.             FISH_CRUSH=atoi(optarg);
  748.             break;
  749.         case 'u':
  750.             usage();
  751.             exit(1);
  752.             break;
  753.         case 'w':
  754.             WIDTH=atoi(optarg);
  755.             break;
  756.         case '?':
  757.             usage();
  758.             exit(1);
  759.             break;
  760.         }
  761.     }
  762.     ALLCELLS=WIDTH*HEIGHT;
  763.     SOMECELLS=ALLCELLS/6;
  764.     SHARK_START=ALLCELLS / 200;
  765.     FISH_START=30 * SHARK_START;
  766.     if (Rflag || Eflag)
  767.         Rflag=1;
  768. }
  769.  
  770. clear_ahead(off)
  771. int off;
  772. {
  773.     static int xoffset, yoffset, i;
  774.     Display *dpy = XtDisplay(population);
  775.     Window win = XtWindow(population);
  776.  
  777.     if ((Pop->width - off) < AHEAD)
  778.         xoffset = off + AHEAD - Pop->width;
  779.     else
  780.         xoffset = off + AHEAD;
  781.     XDrawLine(dpy, win, Egc, xoffset, 0, xoffset, Pop->height);
  782. }
  783.  
  784. usage()
  785. {
  786.     fprintf(stderr,"usage: xwator [-CEPe] [-R res] [-w width] [-h height]\n");
  787.     fprintf(stderr,"\t[-M SHARK_MUTATE] [-S SHARK_SPAWN] [-T SHARK_STARVE]\n");
  788.     fprintf(stderr,"\t[-m FISH_MUTATE] [-s FISH_SPAWN] [-t FISH_CRUSH]\n");
  789.     fprintf(stderr,"\tWhere :\n\t'-C' indicates display population curves\n");
  790.     fprintf(stderr,"\t'-E' indicates use full screen\n");
  791.     fprintf(stderr,"\t'-P' indicates suppress population return maps\n");
  792.     fprintf(stderr,"\t'-c' indicates continue computing\n");
  793.     fprintf(stderr,"\t'-e' indicates erase screen every PPL generations\n");
  794.     fprintf(stderr,"\tDefaults :\n\twidth=100 height=80\n");
  795.     fprintf(stderr,"\tSHARK_SPAWN=10 SHARK_MUTATE=400 SHARK_STARVE=2\n");
  796.     fprintf(stderr,"\tFISH_SPAWN=7 FISH_MUTATE=400 FISH_CRUSH=500\n");
  797. }
  798.  
  799. void
  800. quit(w, call_value)
  801. Widget w;
  802. XmAnyCallbackStruct *call_value;
  803. {
  804.     printf("Xwator: exiting after %d generations\n",generations);
  805.     exit(0);
  806. }
  807.  
  808. void
  809. start_swimming()
  810. {
  811.     if(work_proc_id)
  812.         XtRemoveWorkProc(work_proc_id);
  813.     /*
  814.      * Register go() as a WorkProc.
  815.      */
  816.     work_proc_id = XtAddWorkProc(go, canvas);
  817. }
  818.  
  819. void stop_swimming()
  820. {
  821.     if(work_proc_id)
  822.         XtRemoveWorkProc(work_proc_id);
  823.     work_proc_id = (XtWorkProcId)NULL; 
  824. }
  825.  
  826. init_buffer()
  827. {
  828.     int i;
  829.  
  830.     for(i=0;i<MAXCOLOR;i++) {
  831.         points.npoints[i] = 0;
  832.         rects.nrects[i] = 0;
  833.     }
  834. }
  835.  
  836. ega_bit(w, data, index, x , y)
  837. Widget      w;
  838. struct image_data *data;
  839. int         x,y,index;
  840. {
  841.     XDrawPoint (XtDisplay(w), data->pix, Data->gc[index], x, y);
  842.     if(XtIsRealized(w))
  843.         XDrawPoint (XtDisplay(w), XtWindow(w), Data->gc[index],x,y);
  844. }
  845.  
  846. buffer_box(w, data, color, x , y)
  847. Widget      w;
  848. struct image_data *data;
  849. int         color, x, y;
  850. {
  851.     Arg wargs[3];
  852.     Pixel fore, back;
  853.  
  854.     if(rects.nrects[color] == MAXPOINTS - 1){
  855.       /*
  856.        * If the buffer is full, set the foreground color
  857.        * of the graphics context and draw the rectangles in the pixmap.
  858.        */
  859.         /* set the fill style and tiling pattern for rectangles */
  860.         XSetFillStyle(XtDisplay(canvas), Data->gc[color], FillTiled);
  861.         XtSetArg(wargs[0], XtNforeground, &fore);
  862.         XtSetArg(wargs[1], XtNbackground, &back);
  863.         XtGetValues(canvas, wargs, 2);
  864.         XSetTile(XtDisplay(canvas), Data->gc[color], 
  865.             XmGetPixmap(XtScreen(canvas),patterns[color],
  866.             color, 0));
  867.           XFillRectangles(XtDisplay(canvas), data->pix, Data->gc[color], 
  868.                        rects.coord[color], rects.nrects[color]);
  869.           /*
  870.            * Reset the buffer.
  871.            */
  872.           rects.nrects[color] = 0;
  873.         XSetFillStyle(XtDisplay(canvas), Data->gc[color], FillSolid);
  874.     }
  875.     /*
  876.      * Store the rectangles in the buffer according to its color.
  877.      */
  878.     rects.coord[color][rects.nrects[color]].x = x;
  879.     rects.coord[color][rects.nrects[color]].y = y;
  880.     rects.coord[color][rects.nrects[color]].width = WRES;
  881.     rects.coord[color][rects.nrects[color]].height = HRES;
  882.     rects.nrects[color] += 1;
  883. }
  884.  
  885. buffer_bit(w, data, color, x , y)
  886. Widget      w;
  887. struct image_data *data;
  888. int         color, x,y;
  889. {
  890.  
  891.     if(points.npoints[color] == MAXPOINTS - 1){
  892.       /*
  893.        * If the buffer is full, set the foreground color
  894.        * of the graphics context and draw the points in the pixmap.
  895.        */
  896.           XDrawPoints (XtDisplay(canvas), data->pix, Data->gc[color], 
  897.                        points.coord[color], points.npoints[color], 
  898.                        CoordModeOrigin);
  899.           /*
  900.            * Reset the buffer.
  901.            */
  902.           points.npoints[color] = 0;
  903.     }
  904.     /*
  905.      * Store the point in the buffer according to its color.
  906.      */
  907.     points.coord[color][points.npoints[color]].x = x;
  908.     points.coord[color][points.npoints[color]].y = y;
  909.     points.npoints[color] += 1;
  910. }
  911.  
  912. flush_buffer()
  913.     int i;
  914.     Arg wargs[3];
  915.     Pixel fore, back;
  916.  
  917.     /*
  918.      * Check each buffer.
  919.      */
  920.     for(i=0;i<MAXCOLOR;i++) {
  921.       /*
  922.        * If there are any points in this buffer, draw them in the pixmap.
  923.        */
  924.     if (Rflag) {
  925.           if(rects.nrects[i]){
  926.             /* set the fill style and tiling pattern for rectangles */
  927.             XSetFillStyle(XtDisplay(canvas), Data->gc[i],FillTiled);
  928.             XtSetArg(wargs[0], XtNforeground, &fore);
  929.             XtSetArg(wargs[1], XtNbackground, &back);
  930.             XtGetValues(canvas, wargs, 2);
  931.             XSetTile(XtDisplay(canvas), Data->gc[i], 
  932.                 XmGetPixmap(XtScreen(canvas),patterns[i],
  933.                 i, 0));
  934.                   XFillRectangles(XtDisplay(canvas),Data->pix,Data->gc[i],
  935.                            rects.coord[i], rects.nrects[i]);
  936.                 rects.nrects[i] = 0;
  937.             XSetFillStyle(XtDisplay(canvas), Data->gc[i], FillSolid);
  938.           }
  939.     }
  940.     else
  941.           if(points.npoints[i]){
  942.                   XDrawPoints (XtDisplay(canvas), Data->pix, Data->gc[i], 
  943.                            points.coord[i], points.npoints[i], 
  944.                            CoordModeOrigin);
  945.                 points.npoints[i] = 0;
  946.           }
  947.     }
  948.     /* copy the pixmap into the window */
  949.     if(XtIsRealized(canvas))
  950.         XCopyArea(XtDisplay(canvas), Data->pix, XtWindow(canvas), 
  951.             Data->gc[2], xoff, yoff, WIDTH*WRES, HEIGHT*HRES, 
  952.             xoff, yoff);
  953. }
  954.  
  955. void 
  956. curves()
  957. {
  958.     Arg wargs[3];
  959.     int wide, high;
  960.     XmString label;
  961.  
  962.     if (Cflag) {
  963.         Cflag=0;
  964.         if ((wide=(WIDTH*WRES)) > MAX_X)
  965.             wide = MAX_X - 50;
  966.         if ((high=(HEIGHT*HRES)) > MAX_Y)
  967.             high = MAX_Y - 30;
  968.         XtSetArg(wargs[0], XtNwidth, wide);
  969.         XtSetArg(wargs[1], XtNheight, high);
  970.         XtSetValues(framework, wargs,2);
  971.         label = XmStringCreate("CURVES ON", 
  972.                     XmSTRING_DEFAULT_CHARSET);
  973.         XtSetArg(wargs[0], XmNlabelString, label);
  974.         XtSetValues(button[3], wargs,1);
  975.         XtSetArg(wargs[0], XmNtopPosition, 1);
  976.         XtSetArg(wargs[1], XmNrightPosition, 99);
  977.         XtSetValues(canvas, wargs, 2);
  978.         XtUnmanageChild(fish_return);
  979.         XtUnmanageChild(shark_return);
  980.         XtUnmanageChild(population);
  981.     }
  982.     else {
  983.         Cflag=1;
  984.         if ((wide=(2*WIDTH*WRES)) > MAX_X)
  985.             wide = MAX_X - 50;
  986.         if ((high=(3*HEIGHT*HRES)) > MAX_Y)
  987.             high = MAX_Y - 30;
  988.         XtSetArg(wargs[0], XtNwidth, wide);
  989.         XtSetArg(wargs[1], XtNheight, high);
  990.         XtSetValues(framework, wargs,2);
  991.         label = XmStringCreate("CURVES OFF", 
  992.                     XmSTRING_DEFAULT_CHARSET);
  993.         XtSetArg(wargs[0], XmNlabelString, label);
  994.         XtSetValues(button[3], wargs,1);
  995.         XtSetArg(wargs[0], XmNtopPosition, 47);
  996.         XtSetArg(wargs[1], XmNrightPosition, 59);
  997.         XtSetValues(canvas, wargs, 2);
  998.         XtSetArg(wargs[0], XmNbottomPosition, 45);
  999.         XtSetArg(wargs[1], XmNleftPosition, 1);
  1000.         XtSetValues(population, wargs, 2);
  1001.         XtSetArg(wargs[1], XmNleftPosition, 61);
  1002.         XtSetValues(fish_return, wargs, 2);
  1003.         XtSetArg(wargs[0], XmNbottomPosition, 90);
  1004.         XtSetValues(shark_return, wargs, 2);
  1005.         XtManageChild(fish_return);
  1006.         XtManageChild(shark_return);
  1007.         XtManageChild(population);
  1008.         XFillRectangle(XtDisplay(fish_return), XtWindow(fish_return), 
  1009.                 Egc, 0, 0, Fret->width,  Fret->height);
  1010.         XFillRectangle(XtDisplay(shark_return), XtWindow(shark_return), 
  1011.                 Egc, 0, 0, Sret->width,  Sret->height);
  1012.         XFillRectangle(XtDisplay(population), XtWindow(population), 
  1013.                 Egc, 0, 0, Pop->width,  Pop->height);
  1014.         XCopyArea(XtDisplay(fish_return), Fret->pix, XtWindow(fish_return), 
  1015.             Data->gc[2], 0, 0, Fret->width, Fret->height, 0, 0);
  1016.         XCopyArea(XtDisplay(shark_return), Sret->pix, XtWindow(shark_return), 
  1017.             Data->gc[2], 0, 0, Sret->width, Sret->height, 0, 0);
  1018.         XCopyArea(XtDisplay(population), Pop->pix, XtWindow(population), 
  1019.             Data->gc[2], 0, 0, Pop->width, Pop->height, 0, 0);
  1020.     }
  1021. }
  1022.  
  1023. get_color_index(n)
  1024. int n;
  1025. {
  1026.     char *value, option[20];
  1027.     XColor used, exact;
  1028.  
  1029.     sprintf(option, "Color%d", n);
  1030.     value = XGetDefault(dpy, "Wator", option);
  1031.     if (!value) value = color_names[n];
  1032.     XAllocNamedColor(dpy, DefaultColormap(dpy,0),value,&used,&exact);
  1033.     colors[n] = (mono) ? WhitePixel(dpy,0) : used.pixel;
  1034.     return(colors[n]);
  1035. }
  1036.  
  1037.